import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ShaderMaskDemo extends StatefulWidget {
  const ShaderMaskDemo({Key? key}) : super(key: key);

  @override
  State<ShaderMaskDemo> createState() => _ShaderMaskDemoState();
}

class _ShaderMaskDemoState extends State<ShaderMaskDemo>
    with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _animation;
  late ui.Image fillImage;
  var isImageLoaded = false;

  @override
  void initState() {
    loadImage();
    _animationController =
        AnimationController(duration: const Duration(seconds: 4), vsync: this);
    _animation = Tween<double>(begin: 0, end: 1.0).animate(CurvedAnimation(
      parent: _animationController,
      curve: Curves.linear,
    ))
      ..addListener(() {
        setState(() {});
      });
    _animationController.repeat();

    super.initState();
  }

  Future<ui.Image> loadImage() async {
    final ByteData data = await rootBundle.load('images/fire.png');
    final Completer<ui.Image> completer = Completer();
    ui.decodeImageFromList(Uint8List.view(data.buffer), (ui.Image img) {
      fillImage = img;
      setState(() {
        isImageLoaded = true;
      });
      return completer.complete(img);
    });
    return completer.future;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ShaderMask'),
        backgroundColor: Colors.red[400]!,
      ),
      backgroundColor: const Color.fromARGB(255, 245, 245, 245),
      body: Center(
        child: isImageLoaded
            ? ShaderMask(
                shaderCallback: (rect) {
                  // return LinearGradient(
                  //   begin: Alignment.centerLeft,
                  //   end: Alignment.centerRight,
                  //   colors: [
                  //     Colors.blue,
                  //     Colors.green[300]!,
                  //     Colors.orange[400]!,
                  //     Colors.red,
                  //   ],
                  //   transform:
                  //       SweepTransform((_animation.value - 0.5) * rect.width, 0.0),
                  // ).createShader(rect);

                  return ImageShader(
                    fillImage,
                    TileMode.decal,
                    TileMode.decal,
                    (Matrix4.identity()
                          ..translate(-20.0 * _animation.value,
                              -150.0 * _animation.value))
                        .storage,
                  );
                },
                blendMode: BlendMode.srcIn,
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Image.asset(
                      'images/logo.png',
                      scale: 2,
                    ),
                    const Text(
                      '岛上码农',
                      style: TextStyle(
                        fontSize: 36.0,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ],
                ),
              )
            : Container(),
      ),
    );
  }

  @override
  void dispose() {
    _animationController.stop();
    _animationController.dispose();
    super.dispose();
  }
}

@immutable
class SweepTransform extends GradientTransform {
  const SweepTransform(this.dx, this.dy);

  final double dx;
  final double dy;

  @override
  Matrix4 transform(Rect bounds, {TextDirection? textDirection}) {
    return Matrix4.identity()..translate(dx, dy);
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is SweepTransform && other.dx == dx && other.dy == dy;
  }

  @override
  int get hashCode => dx.hashCode & dy.hashCode;
}
